#!/usr/bin/python3
# built in module
import sys
from functools import wraps
from CustomException import ProvisionDataError
import argparse
from pathlib import PurePosixPath
from re import sub

# 3rd party module
import pandas as pd
from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import SingleQuotedScalarString, DoubleQuotedScalarString

# custom module
from table import Header as header # table header
from objects import FileSystem, VolumeGroup, LogicalVolume, MountPoint, Permissions, Playbook


'''
Read data from csv
'''
def load_provision(f):
    try:
        # use pandas to load and format input data
        df = pd.read_csv(f)
        df.columns = df.columns.str.strip()
        try:
            for index, row in df.iterrows():
                if pd.isnull(row[header.lv]):
                    raise ProvisionDataError('Logical volume data incomplete!')
                if pd.isnull([header.mp]):
                    raise ProvisionDataError('Mount point data incomplete!')
                # if pd.isnull(row[Header.size_mb]):
                #     raise ProvisionDataError('Size data incomplete!')
                if not pd.isnull(row[header.vg]) and pd.isnull(row[header.pv]):
                    raise ProvisionDataError('Physical volume data incomplete!')

        except ProvisionDataError as e:
            print(e)

    except IOError as e:
        print(e)

    else:
        return df

'''
A decorator to convert dictonory to playbook
'''
def generate_pb(tasks): 
    @wraps(tasks)
    def wrapper(*args,**kwargs):
        yaml = YAML()
        #yaml.preserve_quotes = True
        yaml.explicit_start = True
        newPB = Playbook.create("localhost", tasks(*args,**kwargs))
        yaml.dump(newPB, sys.stdout)
    return wrapper

@generate_pb
def generate_vg(df, OS):
    tasks = []
    for index, row in df.iterrows():
        if OS == "Linux":
            # create vg
            if not pd.isnull(row[header.vg]):
                vg = row[header.vg]
                new_vg = VolumeGroup.create(vg,row[header.pv])
                tasks.append(new_vg)
        if OS == "AIX":
            pass

    return tasks


'''
Build a Ansilbe playbook for creating Volume groups, Logical volumes, Filesystems and Mount points.
Permissions will be apply to each Filesystems according to the csv input as well. 
'''
@generate_pb
def fs(df,OS):
    VG = []
    LV = []
    FS = []
    MP = []
    PERMS = []

    for index, row in df.iterrows():
        if OS == "Linux":
            # create vg
            if not pd.isnull(row[header.vg]):
                vg = row[header.vg]
                new_vg = VolumeGroup.create(vg,row[header.pv])
                VG.append(new_vg)
            # create lv
            new_lv = LogicalVolume.create(vg,row[header.lv],row[header.size])
            LV.append(new_lv)
            # create fs
            new_fs = FileSystem.create('xfs',vg+'/'+row[header.lv])
            FS.append(new_fs)
            # create mount point
            new_mp = MountPoint.create('xfs',row[header.mp],vg,row[header.lv])
            MP.append(new_mp)
            # set permission
            new_perms = Permissions.create(row[header.mp],row[header.owner],row[header.group],to_octal_perms(row[header.perms]))
            PERMS.append(new_perms)

        if OS == "AIX":
            pass

    tasks = VG+LV+FS+MP+PERMS
    return tasks

'''
A function to transcode the permission from -rwx format to octal format.
'''
def to_octal_perms(rwx):

    if len(rwx) == 10:
        perms = sub('d', '', rwx)

    perms = sub('-', '0', perms)
    perms = sub('r', '4', perms)
    perms = sub('w', '2', perms)
    perms = sub('x', '1', perms)
    octal = []

    for i in range(0, 9, 3):
        octal.append(sum(list(map(int, perms[i:i+3]))))

    return ''.join(list(map(str, octal)))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-f", "--fs", help="Filesystem list")
    parser.add_argument("-u", "--user", help="User list")
    parser.add_argument("-i", "--interface", help="NIC interface list")
    args = parser.parse_args()
    if args.fs:
        print(args.fs)
        #generate_fs(load_provision(args.fs),"Linux")
    if args.user:
        print(args.user)
    if args.interface:
        print(args.interface)

    fs(load_provision('test.csv'),"Linux")
    sys.exit()